handlers.rs 的 delete_user 部分:
let res = sqlx::query(
		r#"
		DELETE FROM users
		WHERE id = $1 AND id = $2
		"#,
	)
	.bind(id)
	.bind(caller_id)
	.execute(&pool)
	.await
	.map_err(|e| internal_err(e))?;
在 integration_tests.rs,將登入測試移到 PUT 前方添加並取得 jwt ,在測試 PUT 和 DELETE 時使用 jwt
#[tokio::test]
async fn integration_create_get_update_delete_user_flow() {
    // ...
    
	// POST /users/login -> 成功
    let res = client
        .post(format!("{}/users/login", base_url))
        .json(&serde_json::json!({
            "username_or_email": "user1",
            "password": "password"
        }))
        .send()
        .await
        .unwrap();
    assert_eq!(res.status(), StatusCode::OK);
	
	let login_body: Value = res.json().await.unwrap();
	let jwt = login_body
		.get("access_token")
		.and_then(|v| v.as_str())
		.expect("login response should contain string field `access_token`");
    // PUT /users/{id} - 成功
    let res = client
        .put(format!("{}/users/{}", base_url, id))
		.bearer_auth(jwt)
        .json(&serde_json::json!({"username": "new_user1"}))
        .send()
        .await
        .unwrap();
    assert_eq!(res.status(), StatusCode::OK);
    // DELETE /users/{id} -> 成功
    let res = client
        .delete(format!("{}/users/{}", base_url, id))
		.bearer_auth(jwt)
        .send()
        .await
        .unwrap();
    assert_eq!(res.status(), StatusCode::NO_CONTENT);
    // ...
}
建立一個針對 Rust 專案的 CI 工作流程,在 push 與 pull_request 時自動跑測試,包含與外部服務(Postgres、Redis)的整合測試場景。
把以下內容放到 .github/workflows/ci.yml:
name: CI
# 在 push 與 pull_request 時觸發
on:
  push:
    branches: ["**"]
  pull_request:
    branches: ["**"]
env:
  # 測試用 Postgres 帳號(與 services.db.env 保持一致)
  POSTGRES_USER: myapp
  POSTGRES_PASSWORD: myapp_pass
  POSTGRES_DB: myapp_db
jobs:
  test:
    name: Run tests
    runs-on: ubuntu-latest
    services:
      # Postgres service 用於測試(對應你的 tests spawn_app 使用)
      postgres:
        image: postgres:18
        env:
          POSTGRES_USER: ${{ env.POSTGRES_USER }}
          POSTGRES_PASSWORD: ${{ env.POSTGRES_PASSWORD }}
          POSTGRES_DB: ${{ env.POSTGRES_DB }}
        ports:
          - 5432:5432
        options: >-
          --health-cmd "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"
          --health-interval 5s
          --health-timeout 5s
          --health-retries 10
      # Redis service
      redis:
        image: redis:8
        ports:
          - 6379:6379
        options: >-
          --health-cmd "redis-cli ping"
          --health-interval 5s
          --health-timeout 5s
          --health-retries 5
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Set up Rust
        uses: dtolnay/gh-actions-rust@stable
        with:
          toolchain: stable
          profile: minimal
      - name: Cache cargo registry and index
        uses: actions/cache@v4
        with:
          path: |
            ~/.cargo/registry
            ~/.cargo/git
            target
          key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            ${{ runner.os }}-cargo-
      - name: Wait for Postgres to be ready
        # Sleep a bit to allow DB initialization; pg_isready run in service but give extra buffer
        run: sleep 5
      - name: Export test env vars
        run: |
          echo "TEST_DATABASE_URL_BASE=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@localhost:5432" >> $GITHUB_ENV
          echo "TEST_REDIS_URL=redis://127.0.0.1:6379/" >> $GITHUB_ENV
      - name: Install system deps for tests (libssl for sqlx)
        run: sudo apt-get update && sudo apt-get install -y libssl-dev pkg-config
      - name: Run cargo test
        env:
          # cargo test 期間可用到 DB 與 REDIS env(spawn_app 會用 TEST_DATABASE_URL_BASE)
          TEST_DATABASE_URL_BASE: ${{ env.TEST_DATABASE_URL_BASE }}
          TEST_REDIS_URL: ${{ env.TEST_REDIS_URL }}
          RUST_LOG: info
        run: cargo test --workspace --verbose --all-features
將程式碼 push 到 GitHub 後,一開始會是黃燈,經過一些時間後,黃燈將轉變成跟下面一樣的綠色勾勾。